<?php
Zend_Loader::loadClass('Lead_Sql_Query_Field');
Zend_Loader::loadClass('Lead_Sql_Query_Orderer');
Zend_Loader::loadClass('Lead_Sql_Query_Factory');

/**
*
* SQL query. Missing many things, but functional.
* 
* 
*/
class Lead_Sql_Query
{

    private $_tables = array();
    
    private $_debug;
    
    private $_fields = array();
    private $_fieldsLocked = false;
    
    private $_joins = array();
    
    private $_whereGroups = array();
    private $_whereGroupOperator = 'AND';
    private $_currentWhereGroup;
    
    private $_orderers = array();
    
    private $_joinedTables = array();
    
    private $_order = array();
    
    private $_isDistinct = false;
    
    public function __construct($debug = false)
    {
        $this->_debug = $debug;
    
    }
    
    
    /**
    * Sets whether the select is distinct
    *
    * @param boolean $boolDistinct true or false
    */
    public function setDistinct($distinct)
    {
        $this->_isDistinct = $distinct;
    }
    
    
    /**
    * Returns whether the select is distinct
    *
    * @return boolean
    */
    public function isDistinct()
    {
        return $this->_isDistinct;
    }
    
    
    /**
    * Adds an orderer.
    *
    * @param unknown_type $fieldName
    * @param unknown_type $sortOrder
    */
    public function addOrderer($orderer)
    {
        $orderer = new Lead_Sql_Query_Orderer($this, $orderer);
        $this->_orderers[] = $orderer;
    }
    
    
    
    /**
    * Returns whether a field is already added.
    *
    * @param Field $field
    * @return unknown
    */
    public function fieldIsAdded(Field $field)
    {
        return (in_array($field, $this->_fields)) ? true : false;
    }
    
    
    /**
    * Adds a field.
    *
    * @param unknown_type $fieldName
    * @param unknown_type $addTable
    */
    public function addField($fieldName, $addTable = false)
    {               
        if(!$this->_fieldsLocked) {
            if($fieldName == '*') {
                Zend_Loader::loadClass('Lead_Sql_Query_AllFields');
                $field = new Lead_Sql_Query_AllFields($this);
                $this->_fields[$field->getSQLName()] = $field;
                $this->_fieldsLocked = true;
            } else {
                $fieldName = explode(".", $fieldName);
                if(sizeof($fieldName) != 2) {
                    throw new Exception('Define table name.');
                }
                $table = array_shift($fieldName);
                if($addTable) {
                    $this->addTable($table);
                }
            
                if($fieldName != "*") {
                    $field = new Lead_Sql_Query_Field($this, $table, array_shift($fieldName));
                } else {
                    $field = new Lead_Sql_Query_AllFields($this, $table);
                }
                
                $this->_fields[$field->getSQLName()] = $field;
            }
        
        } else {
            return false;
        }
    
    }
    
    
    /**
    * Returns whether a table is added.
    *
    * @param LDB_base_table $table
    * @return unknown
    */
    public function tableIsAdded($table)
    {
        return (in_array($table, $this->_tables)) ? true : false;
    }
    
    
    /**
    * Adds a join
    *
    * @param mixed $table Table, either table name or LDB_table object.
    * @param unknown_type $joinType
    * @param unknown_type $joinClause
    */
    public function addJoin($table, $joinType, $joinClause, $alias = false)
    {
        
        if($alias === false)
            $joinName = $table;
        else 
            $joinName = $alias;
                
        if(in_array($joinName, $this->_joinedTables)) {
            $timesArr = array_count_values($this->_joinedTables);
            $alias = $joinName . '_' . ($timesArr[$joinName] + 1);
        }
        
        $this->_joinedTables[] = $joinName;
        $this->_joins[] = Lead_Sql_Query_Factory::join($table, $joinType, $joinClause, $alias);
    }
        
        
    public function tableIsJoined($tableName)
    {
        return (in_array($tableName, $this->_joinedTables));
    }
        
    
    /**
    * Adds a table.
    *
    * @param LDB_base_table $table
    */
    public function addTable($table)
    {
        if(!$this->tableIsAdded($table)) {
            $this->_joinedTables[] = $table;
            $this->_tables[$table] = $table;
        }
        
    }
    
    
    /**
    * Adds a where group.
    *
    * @param unknown_type $operator
    * @return WhereGroup
    */
    public function addWhereGroup($operator = 'AND')
    {
        Zend_Loader::loadClass('Lead_Sql_Query_Where_Group');
        $whereGroup = new Lead_Sql_Query_Where_Group($this, $operator);
        $this->_whereGroups[] = $whereGroup;
        $this->_currentWhereGroup = $whereGroup;
        return $whereGroup;
    }
    
    /**
    * Returns current where group.
    *
    * @return Lead_Sql_Query_Where_Group
    */
    public function getCurrentWhereGroup()
    {
        if(!$this->_currentWhereGroup)
            $this->addWhereGroup();
        return $this->_currentWhereGroup;
    }
    
    
    
    /**
    * Returns SQL for query.
    *
    * @return string
    */
    public function getSQL()
    {
        $fieldNames = array();
        foreach($this->getFields() as $field)
        {
            $fieldNames[] = $field->getSQLName();
        }
        
        $fieldNames = implode(", ", $fieldNames);
    
        $tableNames = array();
        foreach($this->getTables() as $table)
        {
            $tableNames[] = $table;
        }
    
        $tableNames = implode(", ", $tableNames);
    
        $phrase = "SELECT ";
    
        if($this->isDistinct())
            $phrase .= "DISTINCT";
    
        $phrase .= " {$fieldNames} FROM {$tableNames}";
    
    
        $joins = array();
    
        foreach($this->getJoins() as $join)
        {
            $joins[] = $join->getSQL();
        }
    
        $phrase .= implode(" ", $joins);
    
        $wheres = array();
    
        foreach($this->getWhereGroups() as $whereGroup)
        {
            $wherez = $whereGroup->getSQL();
            if($wherez)
                $wheres[] = $wherez;
        }
    
        if(sizeof($wheres) > 0) {
            $phrase .= " WHERE " . implode(" {$this->_whereGroupOperator} ", $wheres);
        }
    
        if(sizeof($this->getOrderers()) > 0) {
            $orders = array();
            foreach($this->getOrderers() as $orderer) {
                $orders[] = $orderer->getSQL();
            }
    
            $phrase .= " ORDER BY " . implode(", ", $orders);
        }
    
    
        if($this->_debug === true) {
            print "<hr />";
            print __FILE__.":";
            $callstack = debug_backtrace();
            print "{$callstack[0]['file']}:{$callstack[0]['line']}<br />";
            print $phrase;
            print "<hr />";
        }
    
        return $phrase;
     
    
    }
   
    
    /**
    * Sets operator used between wheregroups.
    *
    * @param unknown_type $operator
    */
    public function setWhereGroupOperator($operator)
    {
        $this->_whereGroupOperator = $operator;
    }
    
    
    /**
    * Gets operator used between wheregroups.
    *
    * @return unknown
    */
    public function getWhereGroupOperator()
    {
    return $this->_whereGroupOperator;
    }
    
    
    
    
    
    public function getFields()
    {
        return $this->_fields;
    }
    
    
    public function getTables()
    {
        return $this->_tables;
    }
    
    
    public function getJoins()
    {
        return $this->_joins;
    }
    
    
    public function getWhereGroups()
    {
        return $this->_whereGroups;
    }
    
    
    public function getOrderers()
    {
        return $this->_orderers;
    }
    
    
    
    
    
    

}
?>